/*
 * Copyright 2010-2012 Susanta Tewari. <freecode4susant@users.sourceforge.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package coalescent.nb.jobs.properties;

import coalescent.cef.pui.CheckPhylogenyEventImpl;
import coalescent.cef.pui.RunRecursionEventImpl;
import coalescent.nb.jobs.properties.editors.PropertyEditors;
import commons.nb.jobs.properties.*;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import static coalescent.nb.jobs.properties.Propertys_Coa.Range_Theta.of_MinMaxIncrement;
import static coalescent.nb.jobs.properties.Propertys_Coa.*;

/**
 * Creates a builder property from one or more properties.
 *
 * @author Susanta Tewari
 * @version 1.0.0
 * @history Created on Nov 23, 2011
 * @since 1.0.0
 */
public class ComboPropertys_Coa {

    /**
     * Supplies the following properties in {@link RunRecursionEventImpl}. The properties are:
     * <ul>
     * <li>{@code coalescent.builder.KC64.theta = valid double string as specified in } {@link Double#parseDouble(java.lang.String)}</li>
     * </ul>
     *
     * @return a new instance of the builder property
     * @param prefix
     */
    public static ComboProperty KC64(final String prefix) {
        return new ComboPropertyImpl(of_Theta(prefix));
    }

    public static ComboProperty KC64List(String prefix) {
        return new ComboPropertyImpl(of_MinMaxIncrement(prefix));
    }

    /**
     * @param dummy_theta {@code true} if the UI should include a field for {@code theta};
     * {@code false} otherwise
     * @param prefix
     * @return combo property for supplying {@code KC64Data}
     */
    public static ComboProperty KC64_DATA(final boolean dummy_theta, String prefix) {


        // dependent props: an_prop, k69data-builder prop
        final Property an_prop              = of_Data_An("coalescent.builder.An");
        final BuilderProperty k69Data_bProp = Propertys_Coa.of_Builder_K69Data(null);

        an_prop.setKeyPrefix(prefix);
        k69Data_bProp.setKeyPrefix(prefix);
        k69Data_bProp.addSilentProperty(prefix + ".delegate",
                                        "coalescent.cef.pui.pob.Builders_Coa$Data_KC64_K69Data");


        // controller prop
        final Property<String> controller_prop =
            Propertys.ofString("k69DataOptions-controller", "Choose data type",
                               "Choose between Infinite alleles and Infinite Sites data",
                               PropertySets.DATA, "", "kc64DataOptions-k69Data");

        an_prop.setActive(false);
        controller_prop.setPropEditorClass(PropertyEditors.KC64DataOptionsPE.class);
        controller_prop.addDependent(an_prop);
        controller_prop.addDependent(k69Data_bProp);
        controller_prop.setPropertyChangeListenerDelegate(new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {

                final String value = controller_prop.getValue();

                switch (value) {

                    case "kc64DataOptions-an" :
                        an_prop.setActive(true);
                        k69Data_bProp.setActive(false);

                        break;

                    case "kc64DataOptions-k69Data" :
                        an_prop.setActive(false);
                        k69Data_bProp.setActive(true);

                        break;

                    default :
                        throw new IllegalStateException();
                }
            }

        });


        // prepare combo
        final ComboPropertyImpl combo_prop = new ComboPropertyImpl(controller_prop, an_prop);

        combo_prop.addComboProperty(k69Data_bProp);

        if (dummy_theta) combo_prop.addSilentProperty(prefix + ".theta", "1.0");
        else {    // taking care of dummy_theta
            combo_prop.addProperty(of_Theta(prefix));
        }

        return combo_prop;
    }

    /**
     * Supplies the following properties in {@link RunRecursionEventImpl}. The properties are:
     * <ul>
     * <li>{@code coalescent.builder.An.an = valid values are of the format f1^t1_f2^t2... where fi and ti are positive and represent the frequency domain, and the alleles on that frequency domain, respectively}</li>
     * </ul>
     *
     * @return a new instance of the builder property
     * @param prefix
     */
    public static ComboProperty An(String prefix) {
        return new ComboPropertyImpl(of_Data_An(prefix));
    }

    /**
     * Supplies the following properties in {@link RunRecursionEventImpl}. The properties are:
     * <ul>
     * <li>{@code coalescent.builder.K69.theta = valid double string as specified in } {@link Double#parseDouble(java.lang.String)}</li>
     * </ul>
     *
     * @return a new instance of the builder property
     * @param prefix
     */
    public static ComboProperty K69(final String prefix) {
        return new ComboPropertyImpl(of_Theta(prefix));
    }

    /**
     * Supplies the following properties in {@link CheckPhylogenyEventImpl}. The properties are:
     * <ul>
     * <li>{@code coalescent.builder.CheckPPhylogenyAlgo.algorithm}("GUSFIELD", "FOURGAMETES")</li>
     * </ul>
     *
     * @return a new instance of the builder property
     * @param prefix
     */
    public static ComboProperty PHYLOGENY_ALGO(String prefix) {
        return new ComboPropertyImpl(of_Algo_Phylogeny(prefix));
    }

    public static ComboProperty K69List(String prefix) {
        return new ComboPropertyImpl(of_MinMaxIncrement(prefix));
    }

    /**
     * Supplies the following properties in {@link CheckPhylogenyEventImpl}. The properties are:
     * <ul>
     * <li>{@code coalescent.builder.RecursionComputers.exactProb = true | false}</li>
     * <li>{@code coalescent.builder.RecursionComputers.configCounter = true | false}</li>
     * <li>{@code coalescent.builder.RecursionComputers.genealogyCounter = true | false}</li>
     * <li>{@code coalescent.builder.RecursionComputers.configBuilder = true | false}</li>
     * <li>{@code coalescent.builder.RecursionComputers.genealogyBuilder = true | false}</li>
     * </ul>
     *
     * @return a new instance of the builder property
     * @param prefix
     */
    public static ComboProperty Recursion_Computations(String prefix) {

        return new ComboPropertyImpl(Propertys_Coa.of_Comp_K69_ExactProb(prefix),
                                     Propertys_Coa.of_Comp_K69_ConfigCount(prefix),
                                     Propertys_Coa.of_Comp_K69_GenealogyCount(prefix),
                                     Propertys_Coa.of_Comp_K69_ConfigBuilder(prefix),
                                     Propertys_Coa.of_Comp_K69_GenealogyBuilder(prefix));
    }

    /**
     * It contains no prefix as it is not an input to the computation (unlike in console) but lets
     * the user toggle the display. Typical usage:
     * <pre>
     * addJobProperty( CommonsJobPropertys.BOOLEAN_EXE_JOB_PROPERTY(
     *   new VisualizeRecursionCacheDistn(),
     *   ComboPropertys_Coa.Recursion_Cache_Distn_CmdExe())
     * );
     * </pre>
     *
     * @return a new instance of the property
     */
    public static Property<Boolean> Recursion_Cache_Distn_CmdExe() {

        final Property<Boolean> propImpl = Propertys.ofBoolean();

        propImpl.setName("recursion-profile");
        propImpl.setDisplayName("profile recursion cache?");
        propImpl.setShortDescription("Profile the recursion cache distribution");
        propImpl.setPropertySet(PropertySets_Coa.PROFILE);
        propImpl.setValue(false);

        return propImpl;
    }

    /**
     * Private constructor to prevent instantiation.
     */
    private ComboPropertys_Coa() {}
}
